/*
函数/文件编程（成绩统计与分析）学生信息统计和查询每位学生信息包括：学号、姓名、性别、学院、10 门成绩。
共有不超过100 位学的信息存放在ASCII 文件StudentInfo.txt 中；不超过10 个学院的信息存放在CodeInfo.txt 中，性别代码存放在SexInfo.txt 中，均为代码和其对应的名称。要求：
1. 定义至少包含以上学生信息和学院代码的结构体类型和指针（或数组）变量。
2. 函数实现从文件中输入信息到定义的数据中。
3. 函数实现排序(1)：学生平均成绩的降序排序，并输出所有信息到显示屏。
4. 函数实现排序（2）：学生姓名的升序排序，并输出所有信息到显示器。
5. 函数实现查询（1）：根据学号查询学生信息，并输出该生信息，并输出所有信息到显示器。
6. 函数实现查询（2）：根据姓名查询学生信息，并输出该姓名的学生信息，并输出所有信息到显示器。
7. 函数实现查询（3）：根据学院代号列出该学院的所有学生信息，并输出到显示器。
8. 函数实现统计：根据学生平均成绩统计各分数段的人数级所占的百分比，并以直方图方式输出，形式如下：分段人数图形
<60 3（10%）***
60-69 8（…） ********
70-79 7（…） *******
80-89 8（…） ********
>=90 4（…） ****
进入程序后，无条件执行从指定文件名中读入数据；数据读入后，以菜单的形式选择后续的执行：
1. 平均成绩降序排序
2. 姓名升序排序
3. 学号查询
4. 姓名查询
5. 学院学生列表
6. 平均成绩统计
7. 退出
其中的查询模块中，须为循环结构，用户可以选择继续查询，当输入的为-1 时，结束当前查询，返回主菜单。

提高模块**：1. 函数执行需有密码（密码在文件中不得以明文出现）；2. 密码修改模块
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>
int flag = 0;//修改密码用，做标记。
struct student{
	int id, sex, score[10], collage;
	char name[32], sexno[3], collageno[32];
	double ave;
}S[100], temp;//所有数据。sex是性别代号，sexno是性别代号对应的中文。collage是学院代号，collageno是。。。

struct col{
	char collage1[32];
	int n;
}S1[10];//取文件里面的学院。

struct Sex {
	int m;
	char sex1[5];
}S2[2];//取文件里面的性别。

void read(char *file1, char *file2, char *file3, student S[100], col S1[10]) {
	FILE *fp1, *fp2, *fp3;//定义文件指针
	int i, j;
	fp1 = fopen(file1, "r");//打开文件下同。
	fp2 = fopen(file2, "r");
	fp3 = fopen(file3, "r");
	double sum, ave;
	fscanf(fp3, "%d%s", &S2[0].m, S2[0].sex1);//从文件取出数据给结构体，后面的fscanf都一样。
	fscanf(fp3, "%d%s", &S2[1].m, S2[1].sex1);
	for(i = 0; i < 100; i++) {//有很多个学生，只是学生数量
		sum = 0;
		fscanf(fp1, "%d%s%d%d", &S[i].id, S[i].name, &S[i].sex, &S[i].collage);//只是学生数量的前几个数值，一次取文件一个数值，相对应，遇空格结束。
		for(j = 0; j < 10; j++) {//取10个成绩数据。
			fscanf(fp1, "%d", &S[i].score[j]);
			sum += S[i].score[j];
		}
		S[i].ave = sum / 10.0;//平均数
	}
	for(i = 0; i < 10; i++) {//取学院的代号和名字给这个结构体
		fscanf(fp2, "%d%s", &S1[i].n, S1[i].collage1);
	}
	for(i = 0; i < 100; i++) {//对性别和学院代号的改变。细心应该看得懂。
		if(S[i].sex == S2[0].m)
			strcpy(S[i].sexno, S2[0].sex1);
		else strcpy(S[i].sexno, S2[1].sex1);
		for(j = 0; j < 10; j++) {
			if(S[i].collage == S1[j].n - 1)
				strcpy(S[i].collageno, S1[j].collage1);
		}
	}
	fclose(fp1);//关闭文件。
	fclose(fp2);
	fclose(fp3);
}

void rankave(student S[100]) {//平均成绩降序排序.
	int i, j;
	for(i = 0; i  < 100; i++) {//排序.
		for(j = 1; j < 100 - i; j++) {
			if(S[j].ave > S[j-1].ave) {
				temp = S[j];
				S[j] = S[j-1];
				S[j-1] = temp;
			}
		}
	}
	for(i = 0; i < 100; i++) {//输出.
		printf("%d %s %s %s ", S[i].id, S[i].name, S[i].sexno, S[i].collageno);
		for(j = 0; j < 10; j++) {
			printf("%d ", S[i].score[j]);
		}
		printf("%.2lf\n", S[i].ave);
	}
}

void rankname(student S[100]) {//姓名升序排序。和上面一样。。。
	int i, j;
	for(i = 0; i  < 100; i++) {
		for(j = 1; j < 100 - i; j++) {
			if(strcmp(S[j].name, S[j-1].name) > 0) {
				temp = S[j];
				S[j] = S[j-1];
				S[j-1] = temp;
			}
		}
	}
	for(i = 0; i < 100; i++) {
		printf("%d %s %s %s ", S[i].id, S[i].name, S[i].sexno, S[i].collageno);
		for(j = 0; j < 10; j++) {
			printf("%d ", S[i].score[j]);
		}
		printf("%.2lf\n", S[i].ave);
	}
}

void seeid(student S[100]) {//学号查询.就是对照是就输出，应要求，得可以重复查询。
	int a, i, j, ch;
	while(1) {
		printf("请输入要查询的学号：");
		scanf("%d", &a);
		for(i = 0; i < 100; i++) {
			if(a == S[i].id) {
				printf("%d %s %s %s ", S[i].id, S[i].name, S[i].sexno, S[i].collageno);
				for(j = 0; j < 10; j++) {
					printf("%d ", S[i].score[j]);
				}
				printf("%.2lf\n", S[i].ave);
			}
		}
		printf("输入-1返回主菜单,按任意数字继续查询:");
		scanf("%d", &ch);
		if(ch == -1)
			return ;
	}
}

void seename(student S[100]) {////姓名查询.就是对照是就输出，应要求，得可以重复查询。一样拉。
	int i, j, ch;
	char a[32];
	while(1) {
		printf("请输入要查询学生的名字:");
		scanf("%s" , a);
		for(i = 0; i < 100; i++) {
			if(strcmp(a, S[i].name) == 0) {
				printf("%d %s %s %s ", S[i].id, S[i].name, S[i].sexno, S[i].collageno);
				for(j = 0; j < 10; j++) {
					printf("%d ", S[i].score[j]);
				}
				printf("%.2lf\n", S[i].ave);
				break;
			}
		}
		printf("输入-1返回主菜单,按任意数字继续查询:");
		scanf("%d", &ch);
		if(ch == -1)
			return ;
	}
}

void stacollage(student S[100]) {//学院学生查询。还是差不多。。。
	int i, j, a;
	printf("请输入学院代号:");
	scanf("%d" , &a);
	for(i = 0; i < 100; i++) {
		if(a == S[i].collage) {
			printf("%d %s %s %s  ", S[i].id, S[i].name, S[i].sexno, S[i].collageno);
			for(j = 0; j < 10; j++) {
				printf("%d ", S[i].score[j]);
			}
			printf("%.2lf\n", S[i].ave);
		}
	}
}

void xinghao(int a) {//平均成绩统计。不多说，做过的。。。
	int i;
	for(i = 0; i < a; i++) 
		printf("*");
	printf("\n");
}
void sta(student S[100]) {
	int i, t = 0, r = 0, e = 0, w = 0, q = 0, a = 0;
	for(i = 0; i < 100 ; i++) {
		a = S[i].ave / 10;
		switch(a) {
		case 10:
		case 9: q++; break;
		case 8: w++; break;
		case 7: e++; break;
		case 6: r++; break;
		default: t++; break;
		}
	}
	printf("分数断          学生人数        图形\n");
	printf("<60             %d(%.2lf%%)     ", t, t / 10 * 100.0); xinghao(t);
	printf("60-69           %d(%.2lf%%)        ", r, r / 10 * 100.0); xinghao(r);
	printf("70-79           %d(%.2lf%%)     ", e, e / 10 * 100.0); xinghao(e);
	printf("80-89           %d(%.2lf%%)     ", w, w / 10 * 100.0); xinghao(w);
	printf(">=90            %d(%.2lf%%)        ", q, q / 10 * 100.0); xinghao(q);
}

char change(char ch[]) {//修改密码系统
	char ch1[32];
	printf("请输入新密码:");
	scanf("%s", ch1);
	strcpy(ch, ch1);//改变密码
	flag = 2;//标记。
	return ch[32];
}

int main() {
	int sele;
	char ch[32] = "mima007", ch1[32];	
	read("C:\\Users\\Administrator\\Desktop\\作业\\StudentInfo.txt", "C:\\Users\\Administrator\\Desktop\\作业\\CodeInfo.txt", "C:\\Users\\Administrator\\Desktop\\作业\\SexInfo.txt", S, S1);//读取文件。
	while(1) {//做菜单，无限循环。
		if(flag == 0 || flag == 2) {//输入密码，判断，只有第一次和修改密码了才需要输入密码。
			if(flag == 2) {//修改密码的情况
				system("cls");
				printf("密码已被修改要访问请重新输入新密码：");
			}
			if(flag == 0) printf("要访问请输入密码：");//一般第一次进入的情况。
			scanf("%s", ch1);
			while(strcmp(ch, ch1) != 0) {//错误的情况
				printf("密码错误请重新输入:");
				scanf("%s", ch1);
			}
			flag = 1;//标记，输过就不用再输了。
		}
		system("cls");//清屏，每一次都清屏。下面是菜单。
		printf("                    #######################\n");
		printf("                    #1. 平均成绩降序排序。#\n");
		printf("                    #2. 姓名升序排序。    #\n");
		printf("                    #3. 学号查询          #\n");
		printf("                    #4. 姓名查询          #\n");
		printf("                    #5. 学院学生查询      #\n");
		printf("                    #6. 平均成绩统计      #\n");
		printf("                    #7. 修改密码          #\n");
		printf("                    #8. 退出              #\n");
		printf("                    #######################\n");
		printf("                            请输入1-8:");
		scanf("%d", &sele);
		switch(sele) {//菜单的功能，也就是对应的虽有函数。
			case 1: rankave(S); break;
			case 2: rankname(S); break;
			case 3: seeid(S); break;
			case 4: seename(S); break;
			case 5: stacollage(S); break;
			case 6: sta(S); break;
			case 7: change(ch); break;
			case 8: exit(0);
			default: printf("error\n");
		}
		system("pause");//暂停，因为有个清屏，不然输出立即就清屏，什么东西都没有了。
	}
	return 0;
}